package org.imraniqbal.mouseland;

import java.util.Vector;

import org.imraniqbal.engine.Direction;
import org.imraniqbal.engine.Game;
import org.imraniqbal.engine.GameEvent;
import org.imraniqbal.engine.GameListener;
import org.imraniqbal.engine.Map;
import org.imraniqbal.engine.Mappable;
import org.imraniqbal.engine.Player;

/**
 * @author  imran
 */
public class Hero extends Player implements GameListener{
	/**
	 * @uml.property  name="numOfTraps"
	 */
	private int numOfTraps;
	private final int MAXNUMTRAP = 2;
	private final int SPAWNX = 1;
	private final int SPAWNY = 7;
	
	/**
	 * Creates a Hero with desired X and Y co-ordinate, Direction will be LEFT by default and number of lives will
	 * be set to one
	 * @param x X coordinate of Hero
	 * @param y Y coordinate of Hero
	 * @author imran
	 */
	public Hero(int x, int y, Direction direction, int numOflives) {
		super(x, y, direction, numOflives);
		setNumOfTraps(MAXNUMTRAP);
	}
	
	/**
	 * Creates a Hero with desired direction, lives and position
	 * @param x X coordinate of Hero
	 * @param y Y coordinate of Hero
	 * @param direction Direction of Hero can be UP DOWN LEFT or RIGHT
	 * @param numOflives Number of lives the Hero has
	 * @author imran
	 */
	public Hero(int x, int y) {
		super(x, y);
		setNumOfTraps(MAXNUMTRAP);
	}

	/**
	 * @return  Number of traps left
	 * @author  imran
	 * @uml.property  name="numOfTraps"
	 */
	public int getNumOfTraps(){
		return numOfTraps;
	}
	
	/**
	 * Changes number of traps to what you set it to
	 * @param numOfTraps  new number of traps
	 * @author  imran
	 * @uml.property  name="numOfTraps"
	 */
	public void setNumOfTraps(int numOfTraps){
		this.numOfTraps = numOfTraps;
	}
	
	/**
	 * Sets down a trap, even when no traps are left, this counts as a move
	 * @param map Map on which trap is to be laid
	 * @author imran
	 */
	public void layTrap(Map map){
		if( getNumOfTraps() == 0){ return; }
		map.addMappable(new Trap(this.getX(), this.getY()));
		setNumOfTraps(getNumOfTraps() - 1);
	}
	/**
	 * Spawns hero
	 * @author imran
	 */
	@Override
	public void spawn(Map map) {
		setX(SPAWNX);
		setY(SPAWNY);
		map.addMappable(this);
		
	}
	/**
	 *  Hero does necessary action based on event
	 *  @author imran
	 */
	@Override
	public void onEvent(GameEvent e) {
		if(!(e.getSource() instanceof Game)){ return; }
		Game g = (Game) e.getSource();
		Vector<Mappable> m = g.getMap().getMappable(getX(), getY());
		if(m == null){
			return;
		}
		for(int i = 0; i < m.size(); i++){
			Mappable mpl = m.get(i);
			if( mpl instanceof Mouse){
				this.die(g.getMap());
			}else if( mpl instanceof Exit){
				((Exit)mpl).action(g, g.getMap());
			}
		}
		//Collision code for tile based games, dealing with things switching spots
		//(this would never be a problem in a non-tile based game)
		
		//universal checking code
		m = g.getMap().getMappable(getOldX(), getOldY());
		if(m == null){ return; }
		for(Mappable mpl : m){
			if( !(mpl instanceof Player) ) { continue; }
			if(((Player)mpl).getOldX() == this.getX() &&
				((Player)mpl).getOldY() == this.getY() ){
				//game specific rule set code below
				this.die(g.getMap());
				}
			}
		}
	/**
	 * @author imran
	 */
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Hero){
			if(((Hero)obj).getX() == this.getX() && ((Hero)obj).getY() == this.getY()){
				return( ((Hero)obj).getDirection() == this.getDirection() &&
						((Hero)obj).getNumOflives() == this.getNumOflives() &&
						((Hero)obj).getNumOfTraps() == this.getNumOfTraps()   );
			}
		}
		return false;
	}

}
